package com.boarsoft.boar.file.action;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.util.LinkedList;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;

import com.boarsoft.bean.ReplyInfo;
import com.boarsoft.boar.app.AppFileBiz;
import com.boarsoft.boar.app.AppInstBiz;
import com.boarsoft.boar.entity.AppFile;
import com.boarsoft.boar.entity.FileInfo;
import com.boarsoft.boar.entity.FileVersion;
import com.boarsoft.boar.file.FileBiz;
import com.boarsoft.boar.file.FileVersionBiz;
import com.boarsoft.boar.service.FileService;
import com.boarsoft.common.Authorized;
import com.boarsoft.common.Util;
import com.boarsoft.common.dao.PagedResult;

/**
 * 基类
 * 
 * @author Mac_J
 *
 */
public abstract class FileAction {
	private static final Logger log = LoggerFactory.getLogger(FileAction.class);

	@Autowired
	protected FileBiz fileBiz;
	@Autowired
	protected FileVersionBiz fileVersionBiz;
	@Autowired
	protected AppFileBiz appFileBiz;
//	@Autowired
	protected FileService fileService;
	@Autowired
	protected AppInstBiz appInstBiz;

	@RequestMapping("/pull.do")
	@Authorized(code = "file.pull")
	public ResponseEntity<Object> pull(HttpServletRequest request, int port, String code) {
		String fp = null;
		String ip = request.getRemoteAddr();
		// 根据地址找到实例
		try {
			fp = fileService.find(ip, port, code);
		} catch (Exception e) {
			log.error("Error on read file {} for {}:{}", code, ip, port, e);
			return ResponseEntity.status(HttpStatus.NOT_ACCEPTABLE).build();
		}
		File f = new File(fp);
		if (!f.exists()) {
			log.error("File {} does not exists for {}:{}", fp, ip, port);
			return ResponseEntity.noContent().build();
		}
		InputStreamResource isr;
		try {
			isr = new InputStreamResource(new FileInputStream(f));
			HttpHeaders headers = new HttpHeaders();
			headers.add("Content-Disposition", String.format("attachment;filename=\"%s\"", f.getName()));
			headers.add("Cache-Control", "no-cache,no-store,must-revalidate");
			headers.add("Pragma", "no-cache");
			headers.add("Expires", "0");
			return ResponseEntity.ok().headers(headers).contentLength(f.length())//
					.contentType(MediaType.parseMediaType("application/text")).body(isr);
		} catch (Exception e) {
			log.error("Error on read file {}", fp, e);
			return ResponseEntity.status(500).build();
		}
	}

	@RequestMapping("/list.do")
	@Authorized(code = "file.list")
	public ReplyInfo<Object> list(String projId, String appId, String key, String orderBy, int pageNo, int pageSize) {
		PagedResult<FileInfo> pr = null;
		if (Util.strIsEmpty(appId)) {
			pr = fileBiz.list(projId, key, orderBy, pageNo, pageSize);
		} else {
			PagedResult<AppFile> afPr = appFileBiz.list(appId, key, orderBy, pageNo, pageSize);
			List<FileInfo> fLt = new LinkedList<>();
			for (AppFile af : afPr.getList()) {
				fLt.add(af.getFile());
			}
			pr = new PagedResult<>(afPr.getTotal(), fLt, pageNo, pageSize);
		}
		return new ReplyInfo<>(true, pr);
	}

	@RequestMapping("/delete.do")
	@Authorized(code = "file.delete")
	public ReplyInfo<Object> delete(String id) {
		// 删除文件的所有版本
		List<FileVersion> fvLt = fileVersionBiz.list(id);
		for (FileVersion fv : fvLt) {
			// 删除此版本在存储中的文件，如果有的话
			try {
				fileService.getFilePath(fv);
				this.deleteFile(fv.getPath());
			} catch (IOException e) {
				log.error("Error on delete file {}", fv.getPath(), e);
				continue;
			}
		}
		// 删除文件，同时删除fileVersion, appFile, appInstFile
		fileBiz.delete(id);
		return ReplyInfo.SUCCESS;
	}

	protected void deleteFile(String fp) throws IOException {
		if (Util.strIsEmpty(fp)) {
			return;
		}
		// 如果是以http打头，表示是一个URL，需要通过代理访问
		if (fp.toLowerCase().startsWith("http")) {
			// TODO 暂不处理
			return;
		}
		Files.deleteIfExists(new File(fp).toPath());
		// TODO 向上删除空目录
	}

	@RequestMapping("/get.do")
	@Authorized(code = "file.get")
	public ReplyInfo<Object> get(String id) {
		FileInfo o = fileBiz.get(id);
		return new ReplyInfo<Object>(true, o);
	}
}